﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WPLDB.Infrastucture.UI.ViewModelBase;
using WPLDB.DA.Interfaces.UI;
using System.ComponentModel.Composition;
using Microsoft.Practices.Prism.Commands;
using System.ComponentModel.Composition.Hosting;
using Microsoft.Practices.Prism.Regions;
using WPLDB.DA.Interfaces.UI.Base;
using Microsoft.Practices.Prism.Events;
using WPLDB.Infrastucture.UI.Events;
using WPLDB.DA.Models;
using WPLDB.Infrastucture.UI.Models;
using WPLDB.Utility.DB;
using WPLDB.Code;
using WPLDB.Infrastucture.IO;
using WPLDB.Utility.Extensions;
using EnvDTE;
using WPLDB.Infrastucture.Package;
using WPLDB.Infrastucture;
using Microsoft.VisualStudio.Shell.Interop;

namespace WPLDB.Package.UI.ViewModel
{
    /// <summary>
    /// This View Model is helps to navigate between the Choose Views
    /// also taken care for creating classes in the called projects.
    /// </summary>
    [Export(typeof(IFooterToolbarViewModel))]
    public class FooterToolbarViewModel : ViewModelBase, IFooterToolbarViewModel
    {

        #region "Variables"

        private IRegionManager _regionManager;
        private int _currentScreenIndex = 1;
        int _minScreenIndex = 1;

        [Import]
        private IChooserModel _chooserModel = null;


        [ImportMany]
        private IEnumerable<IChooseViewModel> _listOfChooseViewModel = null;

        private int _maxScreenIndex;

        private int MaxScreenIndex
        {
            get
            {
                if (_maxScreenIndex == 0 && null != _listOfChooseViewModel)
                    _maxScreenIndex = _listOfChooseViewModel.Select(x => x.Index).Max();
                return _maxScreenIndex;
            }
            set { _maxScreenIndex = value; }
        }

        public ProjectItem ProjectItem { get; set; }

        [Import]
        private IShellView _shellView = null;

        #endregion

        #region "ctor"

        [ImportingConstructor]
        public FooterToolbarViewModel(IFooterToolbarView view, IRegionManager regionManager, IEventAggregator eventAggregator, IChooseDatabaseViewModel chooseDatabaseViewModel)
        {
            _regionManager = regionManager;
            this.View = view;
            this.View.SetViewModel(this);
            ChangeChooseView(chooseDatabaseViewModel);
            eventAggregator.GetEvent<ChooseViewChangedEvent<object>>().Subscribe(param => this.CatchEvent(param));

        }



        #endregion

        #region "Interface Implementation"
        public DA.Interfaces.UI.Base.IBaseView View
        {
            get;
            set;
        }

        #endregion

        #region "Command"

        private DelegateCommand<object> _previousCommand;

        public DelegateCommand<object> PreviousCommand
        {
            get
            {
                return _previousCommand ??
                    (_previousCommand = new DelegateCommand<object>(
                        param => this.MovePrevious(),
                        param => this.CanMovePrevious
                        ));
            }
        }

        private DelegateCommand<object> _nextCommand;

        public DelegateCommand<object> NextCommand
        {
            get
            {
                return _nextCommand ??
                    (_nextCommand = new DelegateCommand<object>(
                  param => this.MoveNext(),
                  param => this.CanMoveNext
                  ));
            }
        }

        private DelegateCommand<object> _finishCommand;

        public DelegateCommand<object> FinishCommand
        {
            get
            {
                return _finishCommand ??
                    (_finishCommand = new DelegateCommand<object>(
                  param => this.Finish(),
                  param => this.CanFinish
                  ));
            }

        }

        private DelegateCommand<object> _cancelCommand;

        public DelegateCommand<object> CancelCommand
        {
            get
            {
                return _cancelCommand ??
                    (_cancelCommand = new DelegateCommand<object>(
                  param => this.Cancel(),
                  param => this.CanCancel
                  ));
            }

        }

        #endregion

        #region "Methods"

        private void RefreshCommands()
        {
            PreviousCommand.RaiseCanExecuteChanged();
            NextCommand.RaiseCanExecuteChanged();
            FinishCommand.RaiseCanExecuteChanged();
            CancelCommand.RaiseCanExecuteChanged();
        }

        private IChooseViewModel MoveViewModel(int index)
        {
            if (null == _listOfChooseViewModel) return null;

            IChooseViewModel viewModel = _listOfChooseViewModel.Where(x => x.Index == index).FirstOrDefault();

            return viewModel;
        }

        private void ChangeChooseView(IChooseViewModel viewModel)
        {
            _currentScreenIndex = viewModel.Index;

            viewModel.OnChooserLoad();

            if (!_regionManager.Regions["ChooseRegion"].Views.Contains(viewModel.View))

                _regionManager.RegisterViewWithRegion("ChooseRegion", () => viewModel.View);

            _regionManager.Regions["ChooseRegion"].Activate(viewModel.View);

            RefreshCommands();
        }

        private void ChangeChooseView(int index)
        {
            var viewModel = MoveViewModel(index);
            if (null != viewModel) ChangeChooseView(viewModel);
        }

        private void Cancel()
        {
            Close(true);
        }

        private void Close(bool isCancel = false)
        {
            _shellView.Close(isCancel);
        }

        private void Finish()
        {

            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
            try
            {
                #region "Finish"

                string content = string.Empty;
                string contentHelper = string.Empty;

                if (null != this.ProjectItem)
                {

                    PackageOperations packageOperations = new PackageOperations();
                    _chooserModel.NameSpace = packageOperations.GetNamespace(this.ProjectItem);
                    string fileName = packageOperations.GetClassName(this.ProjectItem);
                    GetContentAndContentHelpter(_chooserModel, fileName, ref content, ref contentHelper);

                    this.ProjectItem = packageOperations.AddFolderAndFile(this.ProjectItem, content, _chooserModel.ClassName, contentHelper);

                }
                else
                {
                    FileOperations fileOperations = new FileOperations();
                    GetContentAndContentHelpter(_chooserModel, "temp", ref content, ref contentHelper);
                    var fileName = fileOperations.Write(@"D:\temp\temp.cs", content, true);
                    var fileNameHelper = fileOperations.Write(@"D:\temp\tempHelper.cs", contentHelper, false);
                }



                #endregion
            }
            finally
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            }
            Close(false);
        }

        private void GetContentAndContentHelpter(IChooserModel chooserModel, string fileName, ref string content, ref string contentHelper)
        {

            List<TableModel> listOfTableModel = new List<TableModel>();

            PackageOperations packageOperations = new PackageOperations();


            WPLDB.Utility.DB.SQLHelper.SetForeignKey(chooserModel.ConnectionString, chooserModel.ListOfTables);

            content += (new CreateTableBaseClassCode()).GenerateClassString();

            if (null != chooserModel && null != chooserModel.ListOfTables)
                listOfTableModel = SQLHelper.GetListOfTableEntity(chooserModel.ConnectionString, chooserModel.ListOfTables);

            CreateEntityClassCode createEntityClassCode = new CreateEntityClassCode(chooserModel.ClassName, listOfTableModel);
            content += createEntityClassCode.GenerateClassString();


            if (null != listOfTableModel)
                foreach (var item in listOfTableModel)
                    if (null != item.Name.Original)
                        content += (new CreateTableClassCode(item)).GenerateClassString();

            content = (new CreateNameSpaceCode(string.Format("{0}.{1}.Designer", chooserModel.NameSpace, fileName), content)).GenerateClassString();
            contentHelper = (new CreateHelperClassCode(listOfTableModel, chooserModel.ConnectionString.InitialCatalog(), chooserModel.ClassName, chooserModel.NameSpace, fileName)).GenerateClassString();


        }

        private void MoveNext()
        {

            try
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
                ChangeChooseView(_currentScreenIndex + 1);
            }
            finally
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            }
        }

        private void MovePrevious()
        {
            try
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
                ChangeChooseView(_currentScreenIndex - 1);

            }
            finally
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            }
        }

        private void CatchEvent(object param)
        {
            PreviousCommand.RaiseCanExecuteChanged();
            NextCommand.RaiseCanExecuteChanged();
            FinishCommand.RaiseCanExecuteChanged();
            CancelCommand.RaiseCanExecuteChanged();
        }


        #endregion

        #region "Predicators"

        public bool CanMovePrevious
        {
            get
            {
                return
                    _currentScreenIndex > _minScreenIndex ? true : false;
            }
        }

        public bool CanMoveNext
        {
            get
            {
                return
                    _currentScreenIndex < MaxScreenIndex
                    && null != _listOfChooseViewModel
                    && _listOfChooseViewModel.Where(x => x.Index == _currentScreenIndex).FirstOrDefault().IsValid;
            }
        }

        public bool CanFinish
        {
            get
            {
                return
                    _currentScreenIndex == MaxScreenIndex
                    && null != _listOfChooseViewModel
                    && _listOfChooseViewModel.Where(x => x.Index == _currentScreenIndex).FirstOrDefault().IsValid;
            }
        }

        public bool CanCancel { get { return true; } }
        #endregion

    }
}
